package com.common.net.api;

import java.util.List;
import java.util.Map;
import io.reactivex.Observable;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.DELETE;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.HEAD;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.Multipart;
import retrofit2.http.OPTIONS;
import retrofit2.http.PATCH;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Part;
import retrofit2.http.Query;
import retrofit2.http.QueryMap;
import retrofit2.http.Streaming;
import retrofit2.http.Url;

/**
 * @Description: 提供 Retrofit 进行网络请求的请求方法
 */
public interface ApiService {

    @GET()
    Observable<ResponseBody> get(@Url String url, @QueryMap Map<String, String> maps);

    /**
     * @FormUrlEncoded表示请求发送编码表单数据，每个键值对需要使用@Field注解
     */
    @FormUrlEncoded
    @POST()
    Observable<ResponseBody> post(@Url() String url, @FieldMap Map<String, String> maps);

    @FormUrlEncoded
    @POST()
    Observable<ResponseBody> postForm(@Url() String url, @FieldMap Map<String, Object> maps);

    @POST()
    Observable<ResponseBody> postBody(@Url() String url, @Body RequestBody requestBody);

    //表明这是一个head请求
    @HEAD()
    Observable<ResponseBody> head(@Url String url, @QueryMap Map<String, String> maps);

    //表明这是一个option请求
    @OPTIONS()
    Observable<ResponseBody> options(@Url String url, @QueryMap Map<String, String> maps);

    @FormUrlEncoded
    @PUT()
    Observable<ResponseBody> put(@Url() String url, @FieldMap Map<String, String> maps);

    @FormUrlEncoded
    @PATCH()
    Observable<ResponseBody> patch(@Url() String url, @FieldMap Map<String, String> maps);

    @FormUrlEncoded
    @DELETE()
    Observable<ResponseBody> delete(@Url() String url, @FieldMap Map<String, String> maps);

    /**
     *  @Streaming 表示响应用字节流的形式返回.如果没使用该注解,默认会把数据全部载入到内存中.
     *  该注解在在下载大文件的特别有用
     *  是注解大文件的，小文件可以忽略不加注释，但是大文件一定需要注释，不然会出现OOM。
     */
    @Streaming
    @GET()
    Observable<ResponseBody> downFile(@Url() String url, @QueryMap Map<String, String> maps);

    /**
     * 文件上传
     */
    @Multipart
    @POST()
    Observable<ResponseBody> uploadFiles(@Url() String url, @Part() List<MultipartBody.Part> parts);


    //==============================参考=====================================

    /**
     * 知识点:
     * 一：
     *   请求方法注解
     *   @GET  @POST  @PUT  @DELETE  @PATCH  @HEAD  @OPTIONS  @HTTP
     *
     * 二：
     *    请求头注解
     *    @Headers  @Header
     *
     * 三：
     *    请求和响应格式注解
     *    @FormUrlEncoded  @Multipart  @Streaming
     *
     * 四: 请求参数类注解
     *     @header
     *     @headers
     *     @URL
     *     @Path
     *     @Query
     *     @QueryMap
     *     @Body 多用于post请求发送非表单数据,比如想要以post方式传递json格式数据
     *     @Filed 多用于post请求中表单字段,Filed和FieldMap需要FormUrlEncoded结合使用
     *     @FiledMap 和@Filed作用一致，用于不确定表单参数
     *     @Part 用于表单字段,Part和PartMap与Multipart注解结合使用,适合文件上传的情况
     *     @PartMap 用于表单字段,默认接受的类型是Map
     */
    /**
     * @Headers的示例
     */

    //使用@Headers添加单个请求头
    @Headers("Cache-Control:public,max-age=120")
    @GET()
    Observable<ResponseBody> getData1(@Url String url, @QueryMap Map<String, String> maps);

    //使用@Headers添加多个请求头
    @Headers({
            "User-Agent:android",
            "Cache-Control:public,max-age=120"
    })
    @GET()
    Observable<ResponseBody> getData2(@Url String url, @QueryMap Map<String, String> maps);

    /**
     * @Header的示例
     */
    @GET("mobile/active")
    Call<ResponseBody> getActive(@Header("token") String token, @Query("id") int activeId);
}
